// MSkeleton.cpp : implementation file
//

#include "stdafx.h"
#include "MSkeleton.h"
#include "../Color Filters/Binary.h"
#include "BinaryErosion.h"
#include "BinaryOpening.h"
#include "../Operators/Difference.h"
#include "../Operators/Mask.h"
#include "../../ImageCores/ImageEx.h"

// CMSkeleton

CMSkeleton::CMSkeleton()
{
}

CMSkeleton::~CMSkeleton()
{
}


// CMSkeleton member functions

BOOL CMSkeleton::Apply(CxImage& srcImage, CxImage& destImage)
{
	// skeleton cuold only be applied to binary images
	CxImage *binaryImage = &srcImage;
	if (!srcImage.IsBinarized())
	{
		binaryImage = new CImageEx();
		binaryImage->Create(srcImage.GetSize(), srcImage.GetBPP());
		CBinary binary;
		binary.Apply(srcImage, *binaryImage);
	}

	CImageEx erosionImagei, openingImagei, skeletonImagei;
	erosionImagei.Create(srcImage.GetSize(), srcImage.GetBPP());
	openingImagei.Create(srcImage.GetSize(), srcImage.GetBPP());
	skeletonImagei.Create(srcImage.GetSize(), srcImage.GetBPP());
	
	CBinaryErosion erosion;
	CBinaryOpening opening;
	CDifference diff;
	CMask unioner(UNION);

	// 1. apply erosion to src image
	erosion.Apply(*binaryImage, erosionImagei);
	// 2. opening the erosion image
	opening.Apply(erosionImagei, openingImagei);
	// 3. get the difference between 1 and 2
	diff.Apply(erosionImagei, openingImagei, skeletonImagei);
	// 4. union the skeleton with dest image
	unioner.Apply(destImage, skeletonImagei);

	while (TRUE)
	{
		// 1. apply erosion to src image
		erosion.Apply(erosionImagei);
		if (((CColorManager*)erosionImagei.GetColorManager())->IsFullBlack())
			break;

		// 2. opening the erosion image
		opening.Apply(erosionImagei, openingImagei);
		// 3. get the difference between 1 and 2
		diff.Apply(erosionImagei, openingImagei, skeletonImagei);
		// 4. union the skeleton with dest image
		unioner.Apply(destImage, skeletonImagei);
	}

	if (!srcImage.IsBinarized())
		delete binaryImage;
	return TRUE;
}